home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fscache / fscacheReadAhead.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  8KB  |  338 lines

  1. /* 
  2.  * fsReadAhead.c 
  3.  *
  4.  *    Routines to implement read ahead.  Read ahead is synchronized
  5.  *    with regular writes to a file to avoid inconsistencies.
  6.  *
  7.  * Copyright 1986 Regents of the University of California.
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fscache/fscacheReadAhead.c,v 9.7 92/06/01 15:31:39 kupfer Exp $ SPRITE (Berkeley)";
  13. #endif not lint
  14.  
  15. #include <sprite.h>
  16. #include <fs.h>
  17. #include <fsutil.h>
  18. #include <fsio.h>
  19. #include <fsStat.h>
  20. #include <fscache.h>
  21. #include <fsNameOps.h>
  22. #include <fsdm.h>
  23. #include <fsrmt.h>
  24. #include <fscacheBlocks.h>
  25.  
  26. /* 
  27.  * Number of blocks to read ahead.  Zero turns off read ahead.
  28.  */
  29. Boolean    fscache_NumReadAheadBlocks = 0;
  30.  
  31. #define    LOCKPTR    (&readAheadPtr->lock)
  32. typedef struct {
  33.     Fscache_FileInfo    *cacheInfoPtr;
  34.     Fscache_ReadAheadInfo    *readAheadPtr;
  35.     Fscache_Block    *blockPtr;
  36.     int            blockNum;
  37. } ReadAheadCallBackData;
  38.  
  39. static void DoReadAhead _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  40. static void IncReadAheadCount _ARGS_((Fscache_ReadAheadInfo *readAheadPtr));
  41. static void DecReadAheadCount _ARGS_((Fscache_ReadAheadInfo *readAheadPtr));
  42.  
  43.  
  44. /*
  45.  *----------------------------------------------------------------------
  46.  *
  47.  * Fscache_ReadAheadInit --
  48.  *
  49.  *    Read ahead the next block in the cache
  50.  *
  51.  * Results:
  52.  *    None.
  53.  *
  54.  * Side effects:
  55.  *    Read ahead process may be started.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59. void
  60. Fscache_ReadAheadInit(readAheadPtr)
  61.     register    Fscache_ReadAheadInfo *readAheadPtr;
  62. {
  63.     bzero((Address) readAheadPtr, sizeof(Fscache_ReadAheadInfo));
  64.     Sync_LockInitDynamic(&readAheadPtr->lock, "Fs:readAheadLock");
  65. }
  66.  
  67. /*
  68.  *----------------------------------------------------------------------
  69.  *
  70.  * Fscache_ReadAheadSyncLockCleanup --
  71.  *
  72.  *    Clean up the Sync_Lock tracing info for the read ahead lock.
  73.  *
  74.  * Results:
  75.  *    None.
  76.  *
  77.  * Side effects:
  78.  *    As above.
  79.  *
  80.  *----------------------------------------------------------------------
  81.  */
  82. /*ARGSUSED*/
  83. void
  84. Fscache_ReadAheadSyncLockCleanup(readAheadPtr)
  85.     Fscache_ReadAheadInfo *readAheadPtr;
  86. {
  87.     Sync_LockClear(&readAheadPtr->lock);
  88. }
  89.  
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * FscacheReadAhead --
  94.  *
  95.  *    Read ahead the next block in the cache
  96.  *
  97.  * Results:
  98.  *    None.
  99.  *
  100.  * Side effects:
  101.  *    Read ahead process may be started.
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105. void
  106. FscacheReadAhead(cacheInfoPtr, blockNum)
  107.     register    Fscache_FileInfo *cacheInfoPtr;
  108.     int                blockNum;
  109. {
  110.     int                i;
  111.     ReadAheadCallBackData    *callBackData;
  112.     Fscache_ReadAheadInfo        *readAheadPtr;
  113.     Boolean            openForWriting;
  114.     Fscache_Block        *blockPtr;
  115.     Boolean            found;
  116.  
  117.     switch (cacheInfoPtr->hdrPtr->fileID.type) {
  118.     case FSIO_LCL_FILE_STREAM: {
  119.         register Fsio_FileIOHandle *handlePtr =
  120.             (Fsio_FileIOHandle *)cacheInfoPtr->hdrPtr;
  121.         openForWriting = (handlePtr->use.write > 0);
  122.         readAheadPtr = &handlePtr->readAhead;
  123.         break;
  124.     }
  125.     case FSIO_RMT_FILE_STREAM: {
  126.         register Fsrmt_FileIOHandle *rmtHandlePtr =
  127.             (Fsrmt_FileIOHandle *)cacheInfoPtr->hdrPtr;
  128.         openForWriting = (rmtHandlePtr->rmt.recovery.use.write > 0);
  129.         readAheadPtr = &rmtHandlePtr->readAhead;
  130.         break;
  131.     }
  132.     default:
  133.         panic("FscacheReadAhead, bad stream type <%d>\n",
  134.         cacheInfoPtr->hdrPtr->fileID.type);
  135.         return;
  136.     }
  137.  
  138.     if (fscache_NumReadAheadBlocks == 0 || openForWriting > 0 ||
  139.         FscacheAllBlocksInCache(cacheInfoPtr)) {
  140.     /*
  141.      * Don't do read ahead if there is no read ahead, the file is
  142.      * open for writing, or all the blocks are already in the cache.
  143.      * Read ahead is disallowed if the file is open for writing because
  144.      * read ahead is done without the handle locked and it is unsafe to
  145.      * be reading and writing a file at the same time.
  146.      */
  147.     return;
  148.     }
  149.     for (i = blockNum; i < blockNum + fscache_NumReadAheadBlocks; i++) {
  150.     if (i * FS_BLOCK_SIZE > cacheInfoPtr->attr.lastByte) {
  151.         return;
  152.     }
  153.     Fscache_FetchBlock(cacheInfoPtr, i,
  154.           FSCACHE_DATA_BLOCK | FSCACHE_DONT_BLOCK | FSCACHE_READ_AHEAD_BLOCK,
  155.           &blockPtr, &found);
  156.     if (found) {
  157.         if (blockPtr != (Fscache_Block *) NIL) {
  158.         Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0, 0);
  159.         }
  160.         continue;
  161.     }
  162.  
  163.     fs_Stats.blockCache.readAheads++;
  164.     IncReadAheadCount(readAheadPtr);
  165.     callBackData = mnew(ReadAheadCallBackData);
  166.     callBackData->cacheInfoPtr = cacheInfoPtr;
  167.     callBackData->readAheadPtr = readAheadPtr;
  168.     callBackData->blockNum = i;
  169.     callBackData->blockPtr = blockPtr;
  170.     Proc_CallFunc(DoReadAhead, (ClientData) callBackData, 0);
  171.     }
  172. }
  173.  
  174. /*
  175.  *----------------------------------------------------------------------
  176.  *
  177.  * DoReadAhead --
  178.  *
  179.  *    Actually read ahead the given block.
  180.  *
  181.  * Results:
  182.  *    None.
  183.  *
  184.  * Side effects:
  185.  *    The given block is read in.
  186.  *
  187.  *----------------------------------------------------------------------
  188.  */
  189. static void
  190. DoReadAhead(data, callInfoPtr)
  191.     ClientData        data;
  192.     Proc_CallInfo    *callInfoPtr;
  193. {
  194.     register    Fscache_FileInfo *cacheInfoPtr;
  195.     register    ReadAheadCallBackData *callBackData;
  196.     register    Fscache_Block    *blockPtr;
  197.     ReturnStatus        status;
  198.  
  199.     callBackData = (ReadAheadCallBackData *) data;
  200.  
  201.     cacheInfoPtr = callBackData->cacheInfoPtr;
  202.     blockPtr = callBackData->blockPtr;
  203.  
  204.     status = (cacheInfoPtr->backendPtr->ioProcs.blockRead)
  205.         (cacheInfoPtr->hdrPtr, blockPtr, (Sync_RemoteWaiter *)NIL);
  206.     if (status != SUCCESS) {
  207.     fs_Stats.blockCache.domainReadFails++;
  208.     Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0, FSCACHE_DELETE_BLOCK);
  209.     } else {
  210.     Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0, 0);
  211.     }
  212.     DecReadAheadCount(callBackData->readAheadPtr);
  213.     free((Address) callBackData);
  214.     callInfoPtr->interval = 0;    /* don't call us again */
  215. }
  216.  
  217. /*
  218.  *----------------------------------------------------------------------------
  219.  *
  220.  * Fscache_WaitForReadAhead --
  221.  *
  222.  *    Block the caller until the read ahead count on this handle goes to
  223.  *    zero.  Called before a write.
  224.  *
  225.  * Results:
  226.  *    None.
  227.  *
  228.  * Side effects:
  229.  *    Blocks read-ahead until FscacheAllowReadAhead is called.
  230.  *
  231.  *----------------------------------------------------------------------------
  232.  *
  233.  */
  234. ENTRY void
  235. Fscache_WaitForReadAhead(readAheadPtr)
  236.     Fscache_ReadAheadInfo *readAheadPtr;
  237. {
  238.     LOCK_MONITOR;
  239.  
  240.     while (readAheadPtr->count > 0) {
  241.     (void) Sync_Wait(&readAheadPtr->done, FALSE);
  242.     }
  243.     readAheadPtr->blocked = TRUE;
  244.  
  245.     UNLOCK_MONITOR;
  246. }
  247.  
  248. /*
  249.  *----------------------------------------------------------------------------
  250.  *
  251.  * Fscache_AllowReadAhead --
  252.  *
  253.  *    Indicate that it is ok to initiate read ahead.  Called when a
  254.  *    write completes.
  255.  *
  256.  * Results:
  257.  *    None.
  258.  *
  259.  * Side effects:
  260.  *    Notifies the okToRead condition.
  261.  *
  262.  *----------------------------------------------------------------------------
  263.  *
  264.  */
  265. ENTRY void
  266. Fscache_AllowReadAhead(readAheadPtr)
  267.     Fscache_ReadAheadInfo *readAheadPtr;
  268. {
  269.     LOCK_MONITOR;
  270.  
  271.     readAheadPtr->blocked = FALSE;
  272.     Sync_Broadcast(&readAheadPtr->okToRead);
  273.  
  274.     UNLOCK_MONITOR;
  275. }
  276.  
  277. /*
  278.  *----------------------------------------------------------------------------
  279.  *
  280.  * IncReadAheadCount --
  281.  *
  282.  *    Increment the number of read aheads on this file.  This will block
  283.  *    if read aheads are blocked because of a write.
  284.  *
  285.  * Results:
  286.  *    None.
  287.  *
  288.  * Side effects:
  289.  *    Increment the number of read aheads on the file.
  290.  *
  291.  *----------------------------------------------------------------------------
  292.  *
  293.  */
  294. static void
  295. IncReadAheadCount(readAheadPtr)
  296.     Fscache_ReadAheadInfo *readAheadPtr;
  297. {
  298.     LOCK_MONITOR;
  299.  
  300.     while (readAheadPtr->blocked) {
  301.     (void) Sync_Wait(&readAheadPtr->okToRead, FALSE);
  302.     }
  303.     readAheadPtr->count++;
  304.  
  305.     UNLOCK_MONITOR;
  306. }
  307.  
  308. /*
  309.  *----------------------------------------------------------------------------
  310.  *
  311.  * DecReadAheadCount --
  312.  *
  313.  *    Decrement the number of read aheads on this file.
  314.  *
  315.  * Results:
  316.  *    None.
  317.  *
  318.  * Side effects:
  319.  *    Read ahead count is decremented and if it goes to zero a broadcast 
  320.  *    is done on the handles condition.
  321.  *
  322.  *----------------------------------------------------------------------------
  323.  *
  324.  */
  325. static void
  326. DecReadAheadCount(readAheadPtr)
  327.     Fscache_ReadAheadInfo *readAheadPtr;
  328. {
  329.     LOCK_MONITOR;
  330.  
  331.     readAheadPtr->count--;
  332.     if (readAheadPtr->count == 0) {
  333.     Sync_Broadcast(&readAheadPtr->done);
  334.     }
  335.  
  336.     UNLOCK_MONITOR;
  337. }
  338.